package com.xunji.user.zip;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

/**
 * 文件夹文件递归拷贝工具类
 * 功能：
 * 1. 递归拷贝源文件夹中的所有文件到目标文件夹
 * 2. 所有文件平铺在目标文件夹中（不保留目录结构）
 * 3. 自动处理文件名冲突（自动重命名）
 * 4. 支持大文件高效拷贝
 * 5. 提供进度回调
 */
public class FileRecursiveCopierUtils {

    public static Logger log = LoggerFactory.getLogger(FileRecursiveCopierUtils.class);


    /**
     * 递归拷贝文件夹中的所有文件到目标文件夹（平铺结构）
     *
     * @param sourceDir 源文件夹路径
     * @param targetDir 目标文件夹路径
     * @throws IOException 拷贝过程中出现的IO异常
     */
    public static void copyFilesRecursively(String sourceDir, String targetDir) throws IOException {
        copyFilesRecursively(sourceDir, targetDir, null);
    }

    /**
     * 递归拷贝文件夹中的所有文件到目标文件夹（带进度回调）
     *
     * @param sourceDir 源文件夹路径
     * @param targetDir 目标文件夹路径
     * @param progress  进度回调接口
     * @throws IOException 拷贝过程中出现的IO异常
     */
    public static void copyFilesRecursively(String sourceDir, String targetDir,
                                            Consumer<CopyProgress> progress) throws IOException {
        Path sourcePath = Paths.get(sourceDir);
        Path targetPath = Paths.get(targetDir);

        // 验证源路径
        if (!Files.exists(sourcePath)) {
            log.error("源文件夹不存在: {}", sourcePath);
            throw new NoSuchFileException("源文件夹不存在: " + sourceDir);
        }
        if (!Files.isDirectory(sourcePath)) {
            log.error("源路径不是文件夹: {}", sourcePath);
            throw new NotDirectoryException("源路径不是文件夹: " + sourceDir);
        }

        // 创建目标文件夹
        if (!Files.exists(targetPath)) {
            Files.createDirectories(targetPath);
        }

        // 计数器
        AtomicInteger totalFiles = new AtomicInteger(0);
        AtomicInteger copiedFiles = new AtomicInteger(0);
        AtomicLong copiedBytes = new AtomicLong(0);

        // 第一次遍历：统计文件总数
        Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                if (Files.isRegularFile(file)) {
                    totalFiles.incrementAndGet();
                }
                return FileVisitResult.CONTINUE;
            }
        });

        // 第二次遍历：执行拷贝
        Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path sourceFile, BasicFileAttributes attrs) throws IOException {
                if (Files.isRegularFile(sourceFile)) {
                    // 获取文件名
                    String fileName = sourceFile.getFileName().toString();

                    // 解决文件名冲突
                    Path targetFile = resolveFileNameConflict(targetPath, fileName);

                    // 拷贝文件
                    long fileSize = Files.size(sourceFile);
                    Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING);

                    // 更新进度
                    int currentCount = copiedFiles.incrementAndGet();
                    long currentBytes = copiedBytes.addAndGet(fileSize);

                    // 回调进度
                    if (progress != null) {
                        progress.accept(new CopyProgress(
                                totalFiles.get(), currentCount, currentBytes
                        ));
                    }
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    /**
     * 解决文件名冲突（自动重命名）
     *
     * @param targetDir 目标文件夹
     * @param fileName  原始文件名
     * @return 解决冲突后的文件路径
     */
    private static Path resolveFileNameConflict(Path targetDir, String fileName) {
        // 基本文件名和扩展名
        String baseName = fileName;
        String extension = "";
        int dotIndex = fileName.lastIndexOf('.');

        if (dotIndex > 0) {
            baseName = fileName.substring(0, dotIndex);
            extension = fileName.substring(dotIndex);
        }

        Path targetFile = targetDir.resolve(fileName);
        int counter = 1;

        // 如果文件已存在，自动添加序号
        while (Files.exists(targetFile)) {
            String newFileName = baseName + " (" + counter + ")" + extension;
            targetFile = targetDir.resolve(newFileName);
            counter++;
        }

        return targetFile;
    }

    /**
     * 拷贝进度信息
     */
    public static class CopyProgress {
        public final int totalFiles;     // 总文件数
        public final int copiedFiles;    // 已拷贝文件数
        public final long copiedBytes;  // 已拷贝字节数

        public CopyProgress(int totalFiles, int copiedFiles, long copiedBytes) {
            this.totalFiles = totalFiles;
            this.copiedFiles = copiedFiles;
            this.copiedBytes = copiedBytes;
        }

        /**
         * 获取拷贝进度百分比
         *
         * @return 0-100的进度值
         */
        public int getPercentage() {
            if (totalFiles == 0) return 100;
            return (int) ((copiedFiles * 100.0) / totalFiles);
        }

        @Override
        public String toString() {
            return String.format("进度: %d%% (%d/%d 文件, %s 已拷贝)",
                    getPercentage(), copiedFiles, totalFiles, formatFileSize(copiedBytes));
        }

        private String formatFileSize(long bytes) {
            if (bytes < 1024) return bytes + " B";
            if (bytes < 1024 * 1024) return String.format("%.1f KB", bytes / 1024.0);
            if (bytes < 1024 * 1024 * 1024) return String.format("%.1f MB", bytes / (1024.0 * 1024));
            return String.format("%.1f GB", bytes / (1024.0 * 1024 * 1024));
        }
    }

    // 原子长整型实现（Java 8+）
    private static class AtomicLong {
        private long value;

        public AtomicLong(long initialValue) {
            this.value = initialValue;
        }

        public long addAndGet(long delta) {
            value += delta;
            return value;
        }

        public long get() {
            return value;
        }
    }

    // ====================== 使用示例 ======================
    public static void main(String[] args) {

        try {
            // 示例1：解压带密码ZIP
            AdvancedCompressionUtils.decompress("D:\\xunji\\xunji-user.7z", "D:\\xunji\\", "123".toCharArray());


            String source = "D:\\xunji\\xunji-user";
            String destination = "D:\\xunji\\xunji-user-copy";

            try {
                System.out.println("开始拷贝文件...");

                // 带进度回调的拷贝
                FileRecursiveCopierUtils.copyFilesRecursively(source, destination, progress -> {
                    System.out.print("\r" + progress);
                    if (progress.getPercentage() == 100) {
                        System.out.println("\n所有文件拷贝完成!");
                    }
                });

                // 简单拷贝（无进度）
                // FileRecursiveCopier.copyFilesRecursively(source, destination);

            } catch (IOException e) {
                System.err.println("文件拷贝失败: " + e.getMessage());
                e.printStackTrace();
            }

        } catch (Exception e) {
            if (e.getMessage().contains("Wrong password") || e.getMessage().contains("requires password")) {
                System.err.println("密码验证失败");
            } else if (e.getMessage().contains("not supported")) {
                System.err.println("不支持的格式");
            } else {
                System.err.println("文件解压失败");
                e.printStackTrace();
            }
        }


    }
}